package org.jeecg.modules.system.udp;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.jeecg.common.api.dto.message.MessageDTO;
import org.jeecg.common.constant.WebsocketConst;
import org.jeecg.common.constant.enums.MessageTypeEnum;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.message.websocket.WebSocket;
import org.jeecg.modules.system.entity.SysDictItem;
import org.jeecg.modules.system.service.ISysDictItemService;
import org.jeecg.modules.tz.entity.TzNetwork;
import org.jeecg.modules.tz.entity.TzNetworkFlow;
import org.jeecg.modules.tz.entity.TzNetworkItem;
import org.jeecg.modules.tz.service.ITzNetworkFlowService;
import org.jeecg.modules.tz.service.ITzNetworkItemService;
import org.jeecg.modules.tz.service.ITzNetworkService;
import org.jeecg.modules.tz.service.ITzThirdService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.Filter;
import org.springframework.integration.annotation.Router;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.annotation.Transformer;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.ip.dsl.Udp;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;

import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;

/**
 * @Version 1.0
 * @Author meng.zhang6@hirain.com
 * @Created Date:2023/2/13 15:09
 * @Description <p>
 * @Modification <p>
 * Date Author Version Description
 * <p>
 * 2023/2/13 15:09 meng.zhang6@hirain.com 1.0 create file
 */

/**
 * UDP消息接收服务
 *
 * @author wliduo[i@dolyw.com]
 * @date 2020/5/20 14:16
 */
@Configuration
public class UdpServer {

    private static final Logger logger = LoggerFactory.getLogger(UdpServer.class);

    @Value("${udp.listeningPort}")
    public Integer listeningPort;

    @Value("${udp.sendingPort}")
    public Integer sendingPort;

    @Value("${udp.sendingIp}")
    public String sendingIp;

    @Autowired
    private WebSocket webSocket;
    @Autowired
    private ISysBaseAPI sysBaseApi;

    @Autowired
    private ITzNetworkFlowService tzNetworkFlowService;
    @Autowired
    private ITzNetworkService tzNetworkService;
    @Autowired
    private ITzNetworkItemService tzNetworkItemService;
    @Autowired
    private ISysDictItemService sysDictItemService;
    @Autowired
    private ITzThirdService tzThirdService;


    /**
     * UDP消息接收服务
     */
    @Bean
    public IntegrationFlow integrationFlow() {
        logger.info("UDP服务启动成功，端口号为: {}", listeningPort);
        return IntegrationFlows.from(Udp.inboundAdapter(listeningPort)).channel("udpChannel").get();
    }

    /**
     * 转换器
     */
    @Transformer(inputChannel = "udpChannel", outputChannel = "udpFilter")
    public String transformer(@Payload byte[] payload, @Headers Map<String, Object> headers) throws UnsupportedEncodingException {
        String message = new String(payload);
//        System.out.println(message);
        // todo 进行数据转换
        return message;
    }


    /**
     * 过滤器
     */
    @Filter(inputChannel = "udpFilter", outputChannel = "udpRouter")
    public boolean filter(String message, @Headers Map<String, Object> headers) {
        // 获取来源Id
        String id = headers.get("id").toString();
        // 获取来源IP，可以进行IP过滤
        String ip = headers.get("ip_address").toString();
        // 获取来源Port
        String port = headers.get("ip_port").toString();
        // todo 信息数据过滤
//        if (true) {
//            // 没有-的数据会被过滤
//            return false;
//        }
        return true;
    }

    /**
     * 路由分发处理器:可以进行分发消息被那个处理器进行处理
     */
    @Router(inputChannel = "udpRouter")
    public String router(String message, @Headers Map<String, Object> headers) {
        // 获取来源Id
        String id = headers.get("id").toString();
        // 获取来源IP，可以进行IP过滤
        String ip = headers.get("ip_address").toString();
        // 获取来源Port
        String port = headers.get("ip_port").toString();
        // todo 筛选，走那个处理器
        if (true) {
            return "udpHandle2";
        }
        return "udpHandle1";
    }

    /**
     * 最终处理器1
     */
    @ServiceActivator(inputChannel = "udpHandle1")
    public void udpMessageHandle(String message) throws Exception {
        // todo 可以进行异步处理
        logger.info("message:" + message);
    }

    /**
     * 最终处理器2
     */
    @ServiceActivator(inputChannel = "udpHandle2")
    public void udpMessageHandle2(String message) throws Exception {
//        String[] split = message.split(",");
//        if(split[2].equals("2000")){
//            logger.info("UDP2:" + message);
//        }
//        logger.info("UDP2:" + message);
        JSONObject obj = new JSONObject();
        obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_TOPIC);


        //将接收到的流量分类保存至数据库中
        //101,192.168.136.13,2000,192.168.136.13,2002,udp,0,0,0,0,0.000000,0.000000,0.000000,0.000000,2024,8,26,14,52,4,0
        String[] split = message.split(",");
        List<TzNetwork> list = tzNetworkService.list();

        LambdaQueryWrapper<TzNetwork> query0 = new LambdaQueryWrapper<>();
        query0.eq(TzNetwork::getTzIp,split[1]);
//        query0.eq(TzNetwork::getStatus,0);
        long count = tzNetworkService.count(query0);


        LambdaQueryWrapper<TzNetworkItem> query = new LambdaQueryWrapper<>();
        query.eq(TzNetworkItem::getLocalIp,split[1]);
        query.eq(TzNetworkItem::getLocalPort,split[2]);
//        long count = tzNetworkItemService.count(query);
        if(count>0){//存在配置
//            logger.info("UDP2:" + message);
            obj.put(WebsocketConst.MSG_ID, "M0001");
            obj.put(WebsocketConst.MSG_TXT, message);
//            logger.info("UDP2:推送到前端");
            webSocket.sendMessage(obj.toJSONString());

            TzNetworkFlow nf = new TzNetworkFlow();
            nf.setTypeCode(split[0]);
            nf.setTzIp(split[1]);
            nf.setTzPort(split[2]);
            nf.setTargetIp(split[3]);
            nf.setTargetPort(split[4]);
            nf.setProtocol(split[5]);
            nf.setSendPacketNum(split[6]);
            nf.setSendBytesNum(split[7]);
            nf.setReceivePacketNum(split[8]);
            nf.setReceiveBytesNum(split[9]);
            nf.setSendPacketRate(split[10]);
            nf.setSendBytesRate(split[11]);
            nf.setReceivePacketRate(split[12]);
            nf.setReceiveBytesRate(split[13]);
            String time = split[14] + "-" + split[15] + "-" + split[16] + " " + split[17] + ":" + split[18] + ":" + split[19];
            nf.setReceiveTime(DateUtils.parseDatetime(time));
            nf.setExtra(split[20]);
            tzNetworkFlowService.save(nf);

            ////推送消息 阈值
            SysDictItem byId = sysDictItemService.getById("1828277420331913217");//接收包速率阈值
            SysDictItem byId2 = sysDictItemService.getById("1828315151367950338");//接收字节速率阈值

            Double itemValue = Double.valueOf(byId.getItemValue());//接收包速率阈值
            Double itemValue2 = Double.valueOf(byId2.getItemValue());//接收包速率阈值
            Double receivePacketRate = Double.valueOf(split[12]);//接收包计速率
            Double receiveBytesRate = Double.valueOf(split[13]);//接受字节速率
            if(receivePacketRate > itemValue){
                String templateContext = "异常流量,异常IP【"+split[1]+"】,异常端口【"+split[2]+"】,接收包速率超限【"+split[12]+"】";
                String title = "告警通知";
                MessageDTO messageDTO = new MessageDTO();
                messageDTO.setToAll(true);
//                messageDTO.setToUser("admin");
                messageDTO.setToUser("admin,tz");
                messageDTO.setTitle("告警推送");
                messageDTO.setType(MessageTypeEnum.XT.getType());
                messageDTO.setIsMarkdown(false);
                messageDTO.setFromUser("system");
                messageDTO.setContent(templateContext);
                sysBaseApi.sendTemplateMessage(messageDTO);
                //将此告警信息推送给软件所
                tzThirdService.notifyLog(title,templateContext);
            }

            if(receiveBytesRate > itemValue2){
                String templateContext = "异常流量,异常IP【"+split[1]+"】,异常端口【"+split[2]+"】,接收字节速率超限【"+receiveBytesRate+"】";
                String title = "告警通知";
                MessageDTO messageDTO = new MessageDTO();
                messageDTO.setToAll(true);
//                messageDTO.setToUser("admin");
                messageDTO.setToUser("admin,tz");
                messageDTO.setTitle("告警推送");
                messageDTO.setType(MessageTypeEnum.XT.getType());
                messageDTO.setIsMarkdown(false);
                messageDTO.setFromUser("system");
                messageDTO.setContent(templateContext);
                sysBaseApi.sendTemplateMessage(messageDTO);
                //将此告警信息推送给软件所
                tzThirdService.notifyLog(title,templateContext);
            }
        }else{

            obj.put(WebsocketConst.MSG_ID, "M0002");
            obj.put(WebsocketConst.MSG_TXT, message);
            webSocket.sendMessage(obj.toJSONString());

            //推送消息
            //推送消息正文内容
            String templateContext = "异常流量,异常IP【"+split[1]+"】,异常端口【"+split[2]+"】";

            String title = "告警推送";
            MessageDTO messageDTO = new MessageDTO();
//            messageDTO.setToUser("admin");
            messageDTO.setToUser("admin,tz");
            messageDTO.setToAll(true);
            messageDTO.setTitle("告警推送");
            messageDTO.setType(MessageTypeEnum.XT.getType());
            messageDTO.setIsMarkdown(false);
            messageDTO.setFromUser("system");
            messageDTO.setContent(templateContext);
            logger.info("------------消息发送对象:{}--------------", JSON.toJSONString(messageDTO));
            sysBaseApi.sendTemplateMessage(messageDTO);
            //将此告警信息推送给软件所
            tzThirdService.notifyLog(title,templateContext);
        }




    }


    public static void main(String[] args) {
        String str = "701,50.0486,49.8133,500.486,157.029,1033.11,10.046,24.2811";
    }
}

